#生成updated_ch.txt

# ch_json解析字幕 --> 生成ch.txt和chdoc.txt --> chatTTS读取chdoc.txt内容生成wav音频存储到output_wav_files --> 读取wav音频时长生成audio_durations.txt --> 将占用时间与ch.txt合并生成updated_ch.txt


import json  
import requests  # 导入 requests 模块以处理 HTTP 请求
import os  # 导入 os 模块以处理文件和目录
import ffmpeg  # 用于音频文件处理
import re  # 用于正则表达式匹配

# 文件配置
input_filename = 'ch.json'  # 输入 JSON 文件名
output_subtitles_file = 'ch.txt'  # 解析后的字幕信息文件名
output_texts_file = 'chdoc.txt'  # 输出纯文本字幕文件名

audio_durations_file = 'audio_durations.txt'# 音频时长文件
output_file = 'updated_ch.txt' # 增加中文音频时长对比
OUTPUT_FOLDER = 'output_wav_files'  # wav输出文件夹

#从字幕片段列表中提取字幕文本和时间偏移信息。
def getTxt(dat):
    out = ''  # 存储所有字幕文本
    datlist = []  # 存储时间偏移和字幕文本
    for i, v in enumerate(dat):  # 遍历字幕片段列表
        tstr = v['utf8']  # 获取当前字幕文本
        out += tstr  # 将字幕文本添加到总字符串中
        offset = 0  # 初始化时间偏移
        if i != 0:
            offset = v['tOffsetMs']  # 如果不是第一个字幕片段，获取其时间偏移
        datlist.append([offset, tstr])  # 将时间偏移和字幕文本添加到列表中
    out = out.replace('\n','')
    return [out, datlist]  

def decodeJosn(fname):
    jdict = None  # 初始化字典
    with open(fname, 'rb') as f:  # 以二进制模式打开文件
        jdict = json.load(f)  # 读取并解析 JSON 数据

    subtxts = jdict['events']  # 提取字幕事件列表
    alltime = 0  # 初始化总时间
    dats = {}  # 初始化字典以存储字幕事件信息
    outstrs = {}  # 初始化字典以存储非空字幕文本

    for i, v in enumerate(subtxts):  # 遍历每个字幕事件
        if i == 0:
            alltime = v['dDurationMs']  # 记录第一个事件的持续时间
        else:
            st = v['tStartMs']  # 获取开始时间
            dt = 0  # 初始化持续时间
            if 'dDurationMs' in v:
                dt = v['dDurationMs']  # 如果有持续时间，则获取

            if 'segs' in v:  # 如果有字幕片段
                txtdat = getTxt(v['segs'])  # 调用函数获取字幕文本和时间偏移

            dats[i] = [st, dt, txtdat[0], txtdat[1]]  # 存储事件相关信息
            if txtdat[0] != '\n' and len(txtdat[0]) > 0:  # 如果字幕文本不为空
                outstrs[i] = [st, dt, txtdat[0]]  # 存储非空字幕文本
    return dats, outstrs  # 返回两个字典


# 定义下载音频的函数
def getAudio(savename, url):
    response = requests.get(url)
    if response.status_code == 200:   
        with open(savename, "wb") as file:
            file.write(response.content)
        print(f"音频文件 {savename} 已成功下载到本地。")
        return True
    else:
        print(f"下载失败，状态码: {response.status_code}")
        return False

# 定义调用 TTS 服务的函数
def chattts(msg, audioname):
    res = requests.post('http://192.168.88.251:9966/tts', data={
        "text": msg,
        "prompt": "",
        "voice": "3333",
        "temperature": 0.3,
        "top_p": 0.7,
        "top_k": 20,
        "skip_refine": 0,
        "custom_voice": 0,
        "is_split": 1
    })
    if res.status_code == 200:
        print(res.json())  
        url = res.json().get('url')
        if url:
            getAudio(audioname, url)
        else:
            print("未能获取音频文件的 URL。")
    else:
        print(f"请求失败，状态码: {res.status_code}")

# 定义处理字幕的函数
def process_subtitles(file_path, output_dir):
    os.makedirs(output_dir, exist_ok=True)
    with open(file_path, 'r', encoding='utf-8') as file:
        lines = file.readlines()
    for index, line in enumerate(lines):
        line = line.strip()
        if line:
            audioname = f'{output_dir}/line_{index + 1}.wav'
            chattts(line, audioname)

# 定义读取wav文件夹里所有音频时长的函数
def get_audio_durations(OUTPUT_FOLDER, audio_durations_file):
    audio_durations = []     # 用于存储文件名和时长的列表
    for filename in os.listdir(OUTPUT_FOLDER):
        if filename.endswith('.wav') and filename.startswith('line_'):
            # 获取文件的索引号
            match = re.search(r'line_(\d+)', filename)  
            if match:
                index = int(match.group(1))
                file_path = os.path.join(OUTPUT_FOLDER, filename)
                # 使用FFmpeg获取音频时长
                try:
                    probe = ffmpeg.probe(file_path)
                    duration_sec = float(probe['format']['duration'])
                    duration_ms = int(duration_sec * 1000)  # 转换为毫秒
                    # 添加到列表中
                    audio_durations.append((index, filename, duration_ms))
                except ffmpeg.Error as e:
                    print(f"无法处理文件 {filename}: {e}")
    audio_durations.sort()  # 根据索引排序
    with open(audio_durations_file, 'w') as f:
        for _, filename, duration_ms in audio_durations:
            f.write(f"{filename}: {duration_ms} ms\n")
    print(f"音频时长已写入 {audio_durations_file}")


# 读取音频时长
def update_ch_file(output_subtitles_file, audio_durations_file, output_file):
    durations = {}
    with open(audio_durations_file, 'r', encoding='utf-8') as f:
        for line in f:
            match = re.match(r'line_(\d+).wav: (\d+) ms', line.strip())
            if match:
                index = int(match.group(1))
                duration = int(match.group(2))
                durations[index] = duration
    updated_lines = []
    with open(output_subtitles_file, 'r', encoding='utf-8') as f:
        for line in f:
            # 匹配行号和列表内容
            match = re.match(r'(\d+): \[(.*)\]', line.strip())
            if match:
                index = int(match.group(1))
                if index in durations:
                    updated_content = f"{match.group(2)}, {durations[index]}"
                    updated_line = f"{index}: [{updated_content}]\n"
                    updated_lines.append(updated_line)
    with open(output_file, 'w', encoding='utf-8') as f:
        f.writelines(updated_lines)
    print(f"更新后的内容已写入 {output_file}")

# 主程序
if __name__ == "__main__":

    dats, outstrs = decodeJosn(input_filename)  # 读取指定 JSON 文件并获取字幕数据

    with open(output_subtitles_file, 'w', encoding='utf-8') as f:     # 打开文件以写入字幕信息
        for k, v in outstrs.items():   # 遍历字幕字典
            f.write(f"{k}: {v}\n")   # 将事件索引和信息写入文件
    print(f"字幕信息已保存到 '{output_subtitles_file}' 文件中。")

    subtitle_texts = [v[2] for v in outstrs.values()]    # 提取每个字幕文本
    


    with open(output_texts_file, 'w', encoding='utf-8') as f:   # 打开文件以写入字幕文本
        f.write('\n'.join(subtitle_texts))    # 将字幕文本拼接并写入文件
    print(f"提取的字幕文本已保存到 '{output_texts_file}' 文件中。")

    # process_subtitles(output_texts_file, OUTPUT_FOLDER) # 处理字幕文件并生成音频
    
    get_audio_durations(OUTPUT_FOLDER, audio_durations_file) #读取wav文件夹里所有音频时长


    update_ch_file(output_subtitles_file, audio_durations_file, output_file)  # 对比音频时长
